<?php


namespace Soen\Container;

use http\Exception\RuntimeException;
use PhpParser\NodeDumper;
use PhpParser\NodeTraverser;
use PhpParser\ParserFactory;
use Psr\Container\ContainerInterface;
use PhpParser\{Node, NodeVisitorAbstract};
use Soen\Container\Aop\ProxyVisitor;
use PhpParser\PrettyPrinter\Standard;
use Swoole\Coroutine;

class ApplicationContext
{
    /**
     * @var Container
     */
    public $container;
    public $contextData;
    function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }


    public function initComponentServer($name, array $args = []){
	    $component = $this->container->get($name);
	    if (!empty($args)){
		    $component['args'] = $args;
	    }
	    $reflection = new \ReflectionClass($component['class']);
	    if (!$reflection) {
		    throw new \ReflectionException('获取组件class' . $name . '异常');
	    }
	    $componentObject = null;
	    if(!empty($component['args'])){
		    $componentObject = $reflection->newInstanceArgs($component['args']);
	    } else {
		    $componentObject = $reflection->newInstance();
	    }
	    return $componentObject;
    }

    public function getComponentServer($name){
        return $this->container->getServer($name);
    }

    public function setComponentServer($name, array $args = []){
	    $componentObject = $this->initComponentServer($name, $args);
        $this->container->setServer($name, $componentObject);
    }

    /**
     * @param $name
     * @param bool $single
     * @param array $args
     * @return mixed|object|null
     */
    function getComponent($name, $single = true, array $args = []){
        if ($single) {
            if ($server = $this->getComponentServer($name)) {
                return $server;
            }
            $this->setComponentServer($name, $args);
            return $this->getComponentServer($name);
        }
	    $componentObject = $this->initComponentServer($name, $args);
	    $component = $this->container->get($name);
	    /* 初始化函数 */
	    $initMethond = (isset($component['init']) && (string)$component['init']) ? $component['init'] : '';
	    if($initMethond){
		    return $componentObject->$initMethond();
	    }
        return $componentObject;
    }

    /**
     * @param $name
     * @param array $args
     * @throws \ReflectionException
     */
//    public function setComponent($name, array $args = []){
//        $component = $this->container->get($name);
//        $reflection = new \ReflectionClass($component['class']);
//        $componentObject = $reflection->newInstanceArgs($args);
//        $this->container->setServer($name, $componentObject);
//    }
    /**
     * @param $key
     * @param $data
     * @param int $cid
     */
    public function setContextData($key, $data, $cid = 0){
        $cid = $cid ?: Coroutine::getCid();
        $this->contextData[$cid][$key] = $data;
    }

    /**
     * @param $key
     * @param int $cid
     * @return mixed
     */
    public function getContextData($key, $cid = 0){
        $cid = $cid ?: Coroutine::getCid();
        return $this->contextData[$cid][$key];
    }
    
}